package zheezes.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * @author hcconquer@gmail.com
 */
public class ZClass {
	/**
	 * @param name
	 *         the full name of the class
	 * @return the class
	 */
	@SuppressWarnings("rawtypes")
	public static Class clazz(String name) {
		try {
			return Class.forName(name);
		} catch (ClassNotFoundException e) {
		}
		return null;
	}
	
	/**
	 * get class static filed's value 
	 * 
	 * @param clazz
	 * @param name
	 *         field name
	 * @param type
	 *         filed generic type
	 * @return the field value
	 */
	@SuppressWarnings({ "rawtypes" })
	public static <T> T getField(Class clazz, String name, Class<T> type) {
		if (clazz == null || name == null) {
			return null;
		}
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			if (field.getName().compareTo(name) != 0) {
				continue;
			}
			int mod = field.getModifiers();
			if ((mod & Modifier.STATIC) == 0) {
				continue;
			}
			try {
				return ZCast.cast(field.get(null), type);
			} catch (IllegalArgumentException e) {
			} catch (IllegalAccessException e) {
			}
		}
		return null;
	}
	
	/**
	 * get instance filed's value
	 * 
	 * @param obj
	 *         the instance
	 * @param name
	 *         field name
	 * @param type
	 *         filed generic type
	 * @return the field value
	 */
	public static <T> T getField(Object obj, String name, Class<T> type) {
		if (obj == null || name == null) {
			return null;
		}
		Field[] fields = obj.getClass().getDeclaredFields();
		for (Field field : fields) {
			if (field.getName().compareTo(name) != 0) {
				continue;
			}
			int mod = field.getModifiers();
			if ((mod & Modifier.STATIC) != 0) {
				continue;
			}
			try {
				return ZCast.cast(field.get(obj), type);
			} catch (IllegalArgumentException e) {
			} catch (IllegalAccessException e) {
			}
		}
		return null;
	}
	
	/**
	 * @param clazz
	 * @param name
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static Method getMethod(Class clazz, String name) {
		Method[] methods = clazz.getMethods();
		for (Method method: methods) {
			if (method.getName().compareTo(name) != 0) {
				continue;
			}
			return method;
		}
		return null;
	}

	/**
	 * create a instance of the class
	 * 
	 * @param clazz
	 *         the type class 
	 * @return the instance of the class
	 */
	public static <T> T newInstance(Class<T> clazz) {
		try {
			return clazz.newInstance();
		} catch (InstantiationException e) {
		} catch (IllegalAccessException e) {
		}
		return null;
	}
	
	/**
	 * create a instance of the class and cast to the type with the 
	 * 
	 * @param clazz
	 *         the type class 
	 * @param type
	 *         the cast type
	 * @return the instance of the class the the type
	 */
	public static <T, C> T newInstance(Class<C> clazz, Class<T> type) {
		return ZCast.cast(newInstance(clazz), type);
	}
	
	@SuppressWarnings("rawtypes")
	public static Object call(Class clazz, String method, Object ...args) {
		Method mthd = getMethod(clazz, method);
		if (mthd == null) {
			return null;
		}
		Object ret = null;
		try {
			ret = mthd.invoke(null, args);
		} catch (IllegalAccessException e) {
		} catch (IllegalArgumentException e) {
		} catch (InvocationTargetException e) {
		}
		return ret;
	}
	
	public static Object call(Object obj, String method, Object ...args) {
		Method mthd = getMethod(obj.getClass(), method);
		if (mthd == null) {
			return null;
		}
		Object ret = null;
		try {
			ret = mthd.invoke(obj, args);
		} catch (IllegalAccessException e) {
		} catch (IllegalArgumentException e) {
		} catch (InvocationTargetException e) {
		}
		return ret;
	}
}
